package cube

import (
	"database/sql"
	"fmt"
	"time"

	log "github.com/sirupsen/logrus"
	"shqsoft.cn/pasnj/base"
	"shqsoft.cn/pasnj/bi/database"
	"shqsoft.cn/pasnj/bi/datapackage"
)

//BuildAll 构建多维数据集所有维度和Cube
func BuildAll(refresh bool) error {
	// if err := BuildAllDimension(); err != nil {
	// 	return err
	// }
	if err := BuildAllBube(refresh); err != nil {
		return err
	}
	return deleteCache()
}

//BuildAllDimension 构建所有维度
func BuildAllDimension() error {
	dp := datapackage.DefaultDP
	log.Info("开始构建维度....")
	for i, dim := range dp.Dimensions {
		if err := buildDimension(&dim, i); err != nil {
			return err
		}
	}
	log.Info("构建维度完成！")
	return nil
}

//BuildAllBube 构建所有维度Cube
func BuildAllBube(refresh bool) error {
	dp := datapackage.DefaultDP
	log.Info("开始构建CUBE....")
	dl := database.DefaultDataLoader
	start, end, err := dl.GetStartEndTime()
	if err != nil {
		return err
	}
	curr := *start
	isEnd := false
	for {
		year, month, _ := curr.Date()
		ms := time.Date(year, month, 1, 0, 0, 0, 0, time.Local)
		if ms.After(*end) {
			break
		}
		me := ms.AddDate(0, 1, -1)
		if me.After(*end) {
			me = *end
			isEnd = true
		}
		// meStr := me.Format("20060102")
		// if err := BuildAllDivision(meStr); err != nil {
		// 	return err
		// }
		// if err := buildAllRelation(&me); err != nil {
		// 	return err
		// }
		for _, cube := range dp.Cubes {
			if !refresh && cube.BuildPeriod == "day" {
				ms = me
			}
			cubeR := cubeMap[cube.Name]
			if err := cubeR.build(&ms, &me); err != nil {
				return err
			}
		}
		if isEnd {
			break
		}
		curr = curr.AddDate(0, 1, 0)
	}
	log.Info("构建CUBE完成!")
	return nil
}

//BuildCubeByName 根据给定的名称和日期构建Cube
func BuildCubeByName(name string, dateStr string, refresh bool) error {
	date, err := time.Parse("20060102", dateStr)
	if err != nil {
		return err
	}
	dl := database.DefaultDataLoader
	_, end, err := dl.GetStartEndTime()
	if err != nil {
		return err
	}
	year, month, _ := date.Date()
	ms := time.Date(year, month, 1, 0, 0, 0, 0, time.Local)
	if ms.After(*end) {
		return fmt.Errorf("指定的日期超出了系统当前日期%s", end.Format("20060102"))
	}
	me := ms.AddDate(0, 1, -1)
	if me.After(*end) {
		me = *end
	}
	cubeR := cubeMap[name]
	if !refresh && cubeR.setting.BuildPeriod == "day" {
		ms = me
	}
	if err := cubeR.build(&ms, &me); err != nil {
		return err
	}
	return nil
}

//BuildDimensionByName 根据给定的名称构建维度
func BuildDimensionByName(name string) error {
	dp := datapackage.DefaultDP
	for i, dim := range dp.Dimensions {
		if dim.Name == name {
			if err := buildDimension(&dim, i); err != nil {
				return err
			}
			break
		}
	}
	return nil
}
func deleteCache() error {
	redisCli := base.RedisClients[0]
	start := int64(0)
	end := int64(99)
	count, err := redisCli.LLen("cache:res").Result()
	if err != nil {
		return err
	}
	for {
		if count == 0 {
			break
		}
		ckeys, err := redisCli.LRange("cache:res", start, end).Result()
		if err != nil {
			return err
		}
		for _, ckey := range ckeys {
			if err := deleteCacheItem(ckey); err != nil {
				return err
			}
		}
		start += end + 1
		end += end + 1
		if count >= start {
			break
		}
	}
	return nil
}
func deleteCacheItem(ckey string) error {
	redisCli := base.RedisClients[0]
	start := int64(0)
	end := int64(99)
	lrKey := ckey + ":lr"
	count, err := redisCli.LLen(lrKey).Result()
	if err != nil {
		return err
	}
	for {
		keys, err := redisCli.LRange(lrKey, start, end).Result()
		if err != nil {
			return err
		}
		for i := range keys {
			keys[i] = ckey + ":h:" + keys[i]
		}
		if err := redisCli.Del(keys...).Err(); err != nil {
			return err
		}
		start += end + 1
		end += end + 1
		if count >= start {
			break
		}
	}
	return nil
}

//buildDimension 构建维度
func buildDimension(dim *datapackage.Dimension, index int) error {
	for _, hie := range dim.Hierarchies {
		dimObj := dimsMap[dim.Name]
		log.Infof("开始构建维度层次%s....", hie.Name)
		hieObj, err := dimObj.NewHierarchy(hie.Name)
		if err != nil {
			return err
		}
		if err := buildHierarchy(hieObj); err != nil {
			return err
		}
		log.Infof("构建维度层次%s完成！", hie.Name)
	}
	return nil
}
func buildHierarchy(hieR *Hierarchy) error {
	dl := database.DefaultDataLoader
	sqlStr := fmt.Sprintf("select * from %s", hieR.setting.Table.Name)
	rows, err := dl.LoadDataBySQL(sqlStr)
	if err != nil {
		return err
	}
	defer rows.Close()
	if err := hieR.Delete(); err != nil {
		return err
	}
	cols, err := base.GetColumns(rows)
	if err != nil {
		return err
	}
	clen := len(cols)
	values := make([]sql.NullString, clen)
	scanArgs := make([]interface{}, clen)
	for i := 0; i < clen; i++ {
		scanArgs[i] = &values[i]
	}
	for rows.Next() {
		err := rows.Scan(scanArgs...)
		if err != nil {
			return err
		}
		if err := hieR.AddData(base.ToMap(cols, values)); err != nil {
			return err
		}
	}
	return nil
}
func buildAllRelation(date *time.Time) error {
	dp := datapackage.DefaultDP
	month := date.Format("200601")
	for _, rela := range dp.Relations {
		rObj := getRelation(&rela, month)
		err := rObj.build()
		if err != nil {
			return err
		}
	}
	return nil
}

//BuildDivision 按照名称、日期构建员工认定
func BuildDivision(name string, date string) error {
	div, err := NewDivision(name)
	if err != nil {
		return err
	}
	return div.build(date)
}

//BuildAllDivision 按照日期构建所有的员工认定
func BuildAllDivision(date string) error {
	diviNames := []string{"comp_acco_divi", "indi_acco_divi", "indi_fana_divi", "indi_loan_divi", "indi_clie_divi"}
	for _, dt := range diviNames {
		div, err := NewDivision(dt)
		if err != nil {
			return err
		}
		err = div.build(date)
		if err != nil {
			return err
		}
	}
	return nil
}
